/**
 * Package: System.ADC
 */

#define ADC_VREF_BG  0xC0               
#define ADC_VREF_VCC 0x40               
#define ADC_VREF_EXT 0x00               

#define ADC22x10    0x0C
#define ADC23x10    0x0D
#define ADC22x200   0x0E
#define ADC23x200   0x0F
#define ADC20x1     0x18
#define ADC21x1     0x19
#define ADC22x1     0x1A
#define ADC23x1     0x1B
#define ADC24x1     0x1C
#define ADC25x1     0x1D

#define ADC0 0
#define ADC1 1
#define ADC2 2
#define ADC3 3
#define ADC4 4
#define ADC5 5
#define ADC6 6
#define ADC7 7

/// <summary>Delivers the digitized measured value from one of the 8 ADC ports. The port number (0..7) has been given as a parameter in the call of ADC_Set(). The result is in the range from 0 to 1023 according to the 10bit resolution of the A/D-Converter. The analog inputs ADC0 to ADC7 can be measured against ground, or differentiation measurement with gain factor of 1/10/100 can be made.</summary>
/// <returns>Measured value at the ADC-Port.</returns>
word ADC_Read               $opc(0x1A)(void);

/// <summary>Reads the measurement value after a successful ADC-Interrupt. The ADC-Interrupt gets triggered after the AD conversion is completed and a new measurement value is available. See ADC_SetInt and ADC_StartInt. The function ADC_Read delivers the digitized measured value from one of the 8 ADC ports. The port number (0..7) has been given as a parameter in the call of ADC_Set(). The result is in the range from 0 to 1023 according to the 10bit resolution of the A/D-Converter. The analog inputs ADC0 to ADC7 can be measured against ground, or differentiation measurement with gain factor of 1/10/100 can be made.</summary>
/// <returns>Measured value at the ADC-Port.</returns>
word ADC_ReadInt            $opc(0x1B)(void);

/// <summary>Initializes the Analog-Digital converter. The reference voltage and the measurement channel number is selected and the A/D converter is prepared for usage. After the measurement the value is read with ADC_Read().</summary>
/// <param name="v_ref">Reference voltage.</param>
/// <param name="channel">Port number (0..7)of ADC (Port A.0 to A.7 at Mega32, Port F.0 to F.7 at Mega128).</param>
void ADC_Set                $opc(0x1C)(byte v_ref, byte channel);

/// <summary>Initializes the Analog-Digital converter for interrupt usage. The reference voltage and the measurement channel number is selected and the A/D converter is prepared for the measurement. An interrupt service routine must be defined. After successful interrupt the value can be read with ADC_ReadInt().</summary>
/// <param name="v_ref">Reference voltage.</param>
/// <param name="channel">Port number (0..7)of ADC (Port A.0 to A.7 at Mega32, Port F.0 to F.7 at Mega128).</param>
void ADC_SetInt             $opc(0x1D)(byte v_ref, byte channel);

/// <summary>The measurement is started if the A/D converter has previously been initialized to interrupt service with a call to ADC_SetInt(). After the measurement is ready, the interrupt gets triggered.</summary>
void ADC_StartInt           $opc(0x1E)(void);

/// <summary>This function disables to the A/D-Converter to reduce power consumption.</summary>
void ADC_Disable            $opc(0x1F)(void);

/// <summary>Reads voltage from a specified channel.</summary>
/// <param name="channel">The channel to read from.</param>
/// <returns>The voltage on the channel.</returns>
word ADC_ReadAdc(byte channel)
{
    ADC_Set(ADC_VREF_BG, channel);
    return ADC_Read();
}

/// <summary>Returns current accumulator voltage.</summary>
/// <returns>The current accumulator voltage.</returns>
float ADC_GetAccumulatorVoltage(void)
{
    return ADC_ReadAdc(0) * 2.56/1023.0 * 2.08;
}